Tagged Unions
A tagged union declaration looks just like a C union, except that it you must specify the @tagged qualifier when declaring it. For example:
@tagged union Foo {
int i;
double d;
char *@fat s;
};
The primary difference with C unions is that a tagged union includes a hidden tag. The tag indicates which member was last written. So, for example:
union Foo x;
x.i = 3;
x.s = "hello";
causes the hidden tag to first indicate that the i member was written, and then is updated to record that the s member was written.
When you attempt to read a member of a tagged union, a check is done on the hidden tag to ensure that this was the last member written, and thus the union contains a valid object of that member’s type. If some other member was last updated, then a Match_Exception will be thrown.
You can test the hidden tag of a tagged union by using the tagcheck operation. For example:
void printFoo(union Foo x) {
if (tagcheck(x.i))
printf("%d",x.i);
else if (tagcheck(x.d))
printf("%g",x.d);
else if (tagcheck(x.s))
printf("%s",x.s);
}
Alternatively, you can use pattern matching (described in the next section) which will ensure that you cover all of the cases properly. For instance, the function above may be rewritten as:
void printFoo(union Foo x) {
switch (x) {
case {.i = i}: printf("%d",i); break;
case {.d = d}: printf("%g",d); break;
case {.s = s}: printf("%s",s); break;
}
}
If we failed to leave out one of the cases in the pattern match, then the compiler would warn us. This is particularly helpful when you add new variants to a tagged union, for then the compiler pinpoints the spots that you need to update in your code. Therefore, we encourage the use of pattern matching where possible.